package rtprtcp

import (
	"bufio"
	"encoding/binary"
	"fmt"
	"gitee.com/general252/gortc/pkg/rtprtcp/rtcp_app"
	"io"
	"sync"
)

type RtpOverTCP struct {
}

func NewRtpOverTCP() *RtpOverTCP {
	return &RtpOverTCP{}
}

const copyBufSize = 2048

var copyBufPool = sync.Pool{
	New: func() any {
		b := make([]byte, copyBufSize)
		return &b
	},
}

// WriteRtpOverTCP 用tcp传输rtp
func (tis *RtpOverTCP) WriteRtpOverTCP(writer io.Writer, data []byte) (int, error) {
	var (
		overData []byte
		dataSize = len(data)
	)

	if dataSize == 0 || writer == nil {
		return 0, fmt.Errorf("no data")
	}

	if dataSize+2 <= copyBufSize {
		pBuff := copyBufPool.Get().(*[]byte)
		buf := *pBuff
		defer copyBufPool.Put(pBuff)

		binary.BigEndian.PutUint16(buf[:2], uint16(dataSize))
		copy(buf[2:], data)
		overData = buf[:dataSize+2]
	} else {
		overData = make([]byte, dataSize+2)
		binary.BigEndian.PutUint16(overData[:2], uint16(dataSize))
		copy(overData[2:], data)
	}

	return writer.Write(overData)
}

func (tis *RtpOverTCP) ReadRtpOverTCP(reader *bufio.Reader) ([]byte, error) {
	var (
		sizeBuff = make([]byte, 2)
		err      error
	)

	if sizeBuff[0], err = reader.ReadByte(); err != nil {
		return nil, err
	}
	if sizeBuff[1], err = reader.ReadByte(); err != nil {
		return nil, err
	}

	packetSize := binary.BigEndian.Uint16(sizeBuff)
	packetData, err := io.ReadAll(io.LimitReader(reader, int64(packetSize)))
	if err != nil {
		return nil, err
	}

	return packetData, nil
}

// CreateApplicationEOF rtcp application EOF
func (tis *RtpOverTCP) CreateApplicationEOF(remoteSSRC uint32) *rtcp_app.App {
	return &rtcp_app.App{
		Source: remoteSSRC,
		Name:   [4]byte{'e', 'o', 'f', ' '},
		App:    make([]byte, 8),
	}
}
